package com.ht.WeNas.utils;

import com.ht.WeNas.config.data.CacheNameEnum;
import org.apache.ibatis.cache.CacheException;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.function.Function;

@Component
public class CacheUtil {
    private final CacheManager cacheManager;
    
    public CacheUtil(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    /**
     * 缓存读取
     * @param name 缓存的名称
     * @param key 缓存的key
     * @return 读取的数据
     */
    public <T, K> T cacheRead(CacheNameEnum name, K key) {
        return this.cacheRead(name, key, null);
    }

    /**
     * 缓存读取
     * @param name 缓存的名称
     * @param key 缓存的key
     * @param directReadFn 缓存失效，直接读取函数
     * @return 读取的数据
     */
    public <T, K> T cacheRead(CacheNameEnum name, K key, Function<K, T> directReadFn) {
        Cache cache = getCache(name);
        Cache.ValueWrapper wrapper = cache.get(key);
        if (wrapper == null) {
            if (directReadFn == null) {
                return null;
            }
            T result = directReadFn.apply(key);
            cache.put(key, result);
            return result;
        }
        Object result = wrapper.get();
        if (result == null) {
            return null;
        } else {
            return (T) result;
        }
    }
    
    /**
     * 直接将数据加入缓存
     * @param name 缓存的名称
     * @param key 缓存的key
     * @param data 需要被缓存的数据
     */
    public <T> void cache(CacheNameEnum name, Serializable key, T data) {
        Cache cache = getCache(name);
        cache.put(key, data);
    }

    public void dropCache(CacheNameEnum name, Object key) {
        Cache cache = this.getCache(name);
        cache.evict(key);
    }

    private Cache getCache(CacheNameEnum name) {
        Cache cache = cacheManager.getCache(name.getName());
        if (cache == null) {
            throw new CacheException();
        }
        return cache;
    }
}
